<?php
/**
 * Eka Framework 0.3.0
 *
 * @copyright Copyright (c) 2008 Alexey Yu. Chuprina <656b61@gmail.com> (http://php-eka.googlecode.com)
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 *
 * @version $Id$
 */

/**
 * Eka_Application_Response
 *
 * @package Application
 * @subpackage Response
 */
class Eka_Application_Response
{
	const CONTENT_TYPE_PLAIN = 'text/plain';
	const CONTENT_TYPE_HTML = 'text/html';
	const CONTENT_TYPE_JSON = 'application/json';
	
	/**
	 * Array of headers
	 *
	 * @var array
	 */
	protected $headers = array();
	
	/**
	 * Array of cookies
	 *
	 * @var array
	 */
	protected $cookies = array();
	
	/**
	 * HTTP response code, use in headers
	 *
	 * @var int
	 */
	protected $code = 200;
	
	/**
	 * Body content
	 *
	 * @var string
	 */
	protected $body;
	
	/**
	 * Set HTTP response code
	 *
	 * @param int $code
	 * @return Eka_Application_Response
	 */
	public function setCode($code)
	{
		$this->code = (int)$code;
		return $this;
	}

	/**
	 * Return HTTP response code
	 *
	 * @return int
	 */
	public function getCode()
	{
		return $this->code;
	}
		
	/**
	 * Set header
	 *
	 * If $replace is true, replaces any headers already defined with that $name.
	 *
	 * @param string $name
	 * @param string $value
	 * @param bool $replace
	 * @return Eka_Application_Response
	 */
	public function setHeader($name, $value, $replace = true)
	{
		$name = $this->formatHeaderName($name);
		$value = (string)$value;
		if ($replace && isset($this->headers[$name])) {
			$this->headers[$name] = array();
		}
		
		$this->headers[$name][] = $value;
		return $this;
	}
	
	/**
	 * Return header value by name
	 *
	 * If headers is not found, return null. If exist many headers, return theirs as array
	 *
	 * @param string $name
	 * @return array|string
	 */
	public function getHeader($name)
	{
		$name = $this->formatHeaderName($name);
		if (!isset($this->headers[$name])) {
			return null;
		}
		return count($this->headers[$name]) == 1 ? $this->headers[$name][0] : $this->headers[$name];
	}
	
	/**
	 * Return array of headers
	 *
	 * @return array
	 */
	public function getHeaders()
	{
		$return = array();
		foreach ($this->headers as $name => $headers) {
			foreach ($headers as $value) {
				$return[] = array('name' => $name, 'value' => $value);
			}
		}
		return $return;
	}
	
	/**
	 * @param string $name
	 * @return bool
	 */
	public function hasHeader($name)
	{
		return isset($this->headers[$this->formatHeaderName($name)]);
	}
	
	/**
	 * Set Content-Type header
	 *
	 * @param $value strign
	 * @return Eka_Application_Response
	 */
	public function setContentTypeHeader($value)
	{
		$this->setHeader('Content-Type', $value, true);
		return $this;
	}
	
	/**
	 * Return Content-Type header
	 *
	 * @return strign
	 */
	public function getContentTypeHeader()
	{
		$res = $this->getHeader('Content-Type');
		if (is_array($res)) {
			$res = array_pop($res);
		}
		return $res;
	}
	
	/**
	 * Set cookie
	 *
	 * @param string $name
	 * @param string $value
	 * @param int $expire Unix timestamp
	 * @param string $path
	 * @param string $domain
	 * @param bool $secure
	 * @param bool $httponly
	 * @return Eka_Application_Response
	 */
	public function setCookie($name, $value = null , $expire = null , $path = null, $domain = null, $secure = false, $httponly = false)
	{
		$this->cookies[] = array($name, $value, $expire, $path, $domain, $secure, $httponly);
		return $this;
	}
	
	/**
	 * Get all cookies from this Response
	 *
	 * @return array
	 */
	public function getCookies()
	{
		return $this->cookies;
	}
	
	/**
	 * Remove all cookies from this Response
	 *
	 * @return Eka_Application_Response
	 */
	public function removeCookies()
	{
		$this->cookies = array();
		return $this;
	}
	
	/**
	 * Set body content
	 *
	 * @param string $content
	 * @return Eka_Application_Response
	 */
	public function setBody($content)
	{
		$this->body = (string)$content;
		return $this;
	}
	
	/**
	 * Append content to body content
	 *
	 * @param string $content
	 * @return Eka_Application_Response
	 */
	public function appendBody($content)
	{
		$this->body .= (string)$content;
		return $this;
	}
	
	/**
	 * Prepend content to body content
	 *
	 * @param string $content
	 * @return Eka_Application_Response
	 */
	public function prependBody($content)
	{
		$this->body = (string)$content . $this->body;
		return $this;
	}
	
	/**
	 * Get body content
	 *
	 * @return string
	 */
	public function getBody()
	{
		return $this->body;
	}
	
	/**
	 * Send headers
	 *
	 * @return Eka_Application_Response
	 */
	public function sendHeaders()
	{
		$codeSent = false;
		
		foreach ($this->headers as $name => $values) {
			foreach ($values as $value) {
				if (!$codeSent) {
					header($name . ': ' . $value, false, $this->code);
					$codeSent = true;
				} else {
					header($name . ': ' . $value, false);
				}
			}
		}
		
		if (!$codeSent) {
			header('HTTP/1.1 ' . $this->code);
		}

		foreach ($this->cookies as $cookie) {
			setcookie($cookie[0], $cookie[1], $cookie[2], $cookie[3], $cookie[4], $cookie[5], $cookie[6]);
		}
		
		return $this;
	}
	
	/**
	 * Send body
	 *
	 * @return Eka_Application_Response
	 */
	public function sendBody() {
		echo $this->body;
		return $this;
	}
	
	/**
	 * Send headers and body
	 *
	 * @return Eka_Application_Response
	 */
	public function send()
	{
		$this->sendHeaders();
		$this->sendBody();
		return $this;
	}
	
	/**
	 * Http redirect
	 *
	 * Sends header Location and all other headers and cookies from this Response.
	 *
	 * @param string $url
	 * @param bool $die
	 * @return Eka_Application_Response
	 */
	public function redirect($url, $die = true)
	{
		$this->setCode(302);
		$this->setHeader('Location', $url, true);
		$this->sendHeaders();
		if ($die) {
			exit;
		}
		return $this;
	}
	
	protected function formatHeaderName($name)
	{
		$name = str_replace('-', ' ', strtolower($name));
		$name = str_replace(' ', '-', ucwords($name));
		return $name;
	}
}